home *** CD-ROM | disk | FTP | other *** search
/ The AGA Experience 3 / AGA Experience Volume 3 (1997)(NFA - SAdENESS)[!].iso / software / utilities / graphics / raylab / source / preproc.c < prev    next >
C/C++ Source or Header  |  1996-07-16  |  9KB  |  331 lines

  1. /*
  2.     name:    preproc.c
  3.  
  4.     Preprocessing
  5.     -------------
  6.  
  7.     This part will do as much optimizing as possible before the
  8.     actual rendering takes place. Not much is done here, but it
  9.     was introduced so that more stuff can be added later (such
  10.     as more automatic bounding, and octree subdivision).
  11.  
  12.  
  13.     This source-code is part of the RayLab 1.1 package, and it is provided
  14.     for your compiling pleasure.  You may use it, change it, re-compile it
  15.     etc., as long as nobody else but you receive the changes/compilations
  16.     that you have made!
  17.  
  18.     You may not use any part(s) of this source-code for your own productions
  19.     without the permission from the author of RayLab. Please read the legal
  20.     information found in the users documentation for RayLab for more details.
  21.  
  22. */
  23.  
  24.  
  25. #include  <stdlib.h>
  26.  
  27. #include  "defs.h"
  28. #include  "extern.h"
  29.  
  30.  
  31. /* ---------------------------------------------------------------------
  32.     Preprocess()
  33.    --------------------------------------------------------------------- */
  34.  
  35. void Preprocess(void)
  36. {
  37.     fprintf(textoutput,"Preprocessing...");
  38.  
  39.     OptimizeAllTransforms();
  40.     AutoBoundObjects();
  41.     RemoveAllUselessTextureTransforms();
  42.  
  43.     if((NeedNoise==TRUE)&&(RenderMethod!=RENDER_QUICKSCAN)) {
  44.         InitNoiseTable();    /* Initialize table for noise functions */
  45.     }
  46.     RndSeed=9761532L;    /* Initialize jitter seed */
  47.  
  48.     fprintf(textoutput,"done\n\n");
  49. }
  50.  
  51.  
  52.  
  53. /* ---------------------------------------------------------------------
  54.     OptimizeAllTransforms() Optimizes all possible transforms
  55.    --------------------------------------------------------------------- */
  56.  
  57. void OptimizeAllTransforms(void)
  58. {
  59.     int    i;
  60.  
  61.     for(i=0;i<NumObjects;i++)  OptimizeObjTransforms(ObjectArray[i]);
  62.     for(i=0;i<Num24Images;i++) OptimizeTransform(&Img24Array[i]->Transform);
  63.     for(i=0;i<Num8Images;i++)  OptimizeTransform(&Img8Array[i]->Transform);
  64. }
  65.  
  66.  
  67. /* ---------------------------------------------------------------------
  68.     OptimizeObjTransforms() Optimizes object transforms
  69.     (recursively for CSG's)
  70.    --------------------------------------------------------------------- */
  71.  
  72. void OptimizeObjTransforms(OBJECT *Obj)
  73. {
  74.     CSG    *csg;
  75.  
  76.     if(Obj->ShapeType==SHAPE_CSG) {
  77.         csg=(CSG *)Obj->Shape;
  78.         OptimizeObjTransforms(csg->Object1);
  79.         OptimizeObjTransforms(csg->Object2);
  80.     }
  81.     OptimizeTransform(&Obj->Transform);
  82.     OptimizeTransform(&Obj->Texture.Transform);
  83. }
  84.  
  85.  
  86. /* ---------------------------------------------------------------------
  87.     OptimizeTransform() Optimizes a single transform
  88.    --------------------------------------------------------------------- */
  89.  
  90. void OptimizeTransform(TRANSFORM *Trans)
  91. {
  92.     int    i,j,k,TType,Combined;
  93.  
  94.  
  95. /* Try to combine successive transfroms of the same kind */
  96.  
  97.     i=0;
  98.     while(i<Trans->NumTransforms) {
  99.         Combined=FALSE;
  100.         j=i+1;
  101.         if(j<Trans->NumTransforms) {
  102.         TType=Trans->Entry[i].Type;
  103.         if(TType==Trans->Entry[j].Type) {
  104.             if(TType==TRANSFORM_MOVE) {
  105.             Trans->Entry[i].Values.x+=Trans->Entry[j].Values.x;
  106.             Trans->Entry[i].Values.y+=Trans->Entry[j].Values.y;
  107.             Trans->Entry[i].Values.z+=Trans->Entry[j].Values.z;
  108.             Combined=TRUE;
  109.             }
  110.             if(TType==TRANSFORM_SCALE) {
  111.             Trans->Entry[i].Values.x*=Trans->Entry[j].Values.x;
  112.             Trans->Entry[i].Values.y*=Trans->Entry[j].Values.y;
  113.             Trans->Entry[i].Values.z*=Trans->Entry[j].Values.z;
  114.             Combined=TRUE;
  115.             }
  116.             if(Combined==TRUE) {
  117.             if(j<(Trans->NumTransforms-1)) {
  118.                 for(k=j+1;k<Trans->NumTransforms;k++) {
  119.                 Trans->Entry[k-1]=Trans->Entry[k];
  120.                 }
  121.             }
  122.             Trans->NumTransforms--;
  123.             }
  124.         }
  125.         }
  126.         if(Combined==FALSE) i++;
  127.     }
  128. }
  129.  
  130.  
  131. /* ---------------------------------------------------------------------
  132.     AutoBoundObjects() calls routines for automatic bounding.
  133.    --------------------------------------------------------------------- */
  134.  
  135. void AutoBoundObjects(void)
  136. {
  137.     OBJECT    *Obj;
  138.     int    i;
  139.  
  140.     for(i=0;i<NumObjects;i++) {
  141.         Obj=ObjectArray[i];
  142.         if(Obj->BoundType==BOUND_NONE) {
  143.         switch (Obj->ShapeType) {
  144.             case SHAPE_TRIANGLELIST:
  145.             BoundTriangleList(Obj);
  146.             break;
  147.             default:
  148.             break;
  149.         }
  150.         }
  151.     }
  152. }
  153.  
  154.  
  155. /* ---------------------------------------------------------------------
  156.     BoundTriangleList() determines the optimal bounding box for
  157.     a given triangle list object.
  158.    --------------------------------------------------------------------- */
  159.  
  160. void BoundTriangleList(OBJECT *Obj)
  161. {
  162.     VECTOR    min,max,corners[3];
  163.     BOX    *BBox;
  164.     TRIANGLELIST *Tri;
  165.     register double    tnx,tny,tnz;
  166.     int    i;
  167.  
  168.     min.x=min.y=min.z=50000.0;
  169.     max.x=max.y=max.z=-50000.0;
  170.  
  171.     Tri=(TRIANGLELIST *)Obj->Shape;
  172.     while(Tri!=NULL) {
  173.         tnx=Tri->Normal.x; tny=Tri->Normal.y; tnz=Tri->Normal.z;
  174.         switch (Tri->Projection) {
  175.         case PROJ_XY:
  176.             for(i=0;i<3;i++) {
  177.             corners[i].x=Tri->Corners[i].u;
  178.             corners[i].y=Tri->Corners[i].v;
  179.             corners[i].z=-(tnx*Tri->Corners[i].u+tny*Tri->Corners[i].v)/tnz;
  180.             }
  181.             break;
  182.         case PROJ_XZ:
  183.             for(i=0;i<3;i++) {
  184.             corners[i].x=Tri->Corners[i].u;
  185.             corners[i].z=Tri->Corners[i].v;
  186.             corners[i].y=-(tnx*Tri->Corners[i].u+tnz*Tri->Corners[i].v)/tny;
  187.             }
  188.             break;
  189.         case PROJ_YZ:
  190.             for(i=0;i<3;i++) {
  191.             corners[i].y=Tri->Corners[i].u;
  192.             corners[i].z=Tri->Corners[i].v;
  193.             corners[i].x=-(tny*Tri->Corners[i].u+tnz*Tri->Corners[i].v)/tnx;
  194.             }
  195.             break;
  196.         }
  197.         for(i=0;i<3;i++) {
  198.         if(corners[i].x<min.x) min.x=corners[i].x;
  199.         if(corners[i].x>max.x) max.x=corners[i].x;
  200.         if(corners[i].y<min.y) min.y=corners[i].y;
  201.         if(corners[i].y>max.y) max.y=corners[i].y;
  202.         if(corners[i].z<min.z) min.z=corners[i].z;
  203.         if(corners[i].z>max.z) max.z=corners[i].z;
  204.         }
  205.         Tri=Tri->NextTriangle;
  206.     }
  207.  
  208.     if((BBox=(BOX *)malloc(sizeof(BOX)))!=NULL) {
  209.         CopyPoint(&BBox->Corners[0],(POINT *)&min);
  210.         CopyPoint(&BBox->Corners[1],(POINT *)&max);
  211.         Obj->BoundType=BOUND_BOX;
  212.         Obj->Bound=(void *)BBox;
  213.         TransformBounding(Obj, &Obj->Transform);
  214.     }
  215. }
  216.  
  217.  
  218. /* ---------------------------------------------------------------------
  219.     TransformBounding() determines the optimal bounding volume
  220.     after it has been transformed.
  221.    --------------------------------------------------------------------- */
  222.  
  223. void TransformBounding(OBJECT *Obj, TRANSFORM *Trans)
  224. {
  225.     BOX    *Box;
  226.     SPHERE    *Sphere;
  227.     POINT    BoxCorners[8];
  228.     VECTOR    Radius;
  229.     double    MaxRadius;
  230.     int    i;
  231.  
  232.     if((Obj->BoundType == BOUND_BOX)||(Obj->BoundType == BOUND_TMPBOX)) {
  233.         Box = (BOX *)Obj->Bound;
  234.         for(i=0;i<8;i++) {
  235.         BoxCorners[i].x = Box->Corners[i&0x01].x;
  236.         BoxCorners[i].y = Box->Corners[(i>>1)&0x01].y;
  237.         BoxCorners[i].z = Box->Corners[(i>>2)&0x01].z;
  238.         }
  239.         Box->Corners[0].x = Box->Corners[0].y =  Box->Corners[0].z = maxcoord;
  240.         Box->Corners[1].x = Box->Corners[1].y =  Box->Corners[1].z = mincoord;
  241.         for(i=0;i<8;i++) {
  242.         ForwdTransformPoint(&BoxCorners[i], Trans);
  243.         if(BoxCorners[i].x<Box->Corners[0].x) Box->Corners[0].x = BoxCorners[i].x;
  244.         if(BoxCorners[i].y<Box->Corners[0].y) Box->Corners[0].y = BoxCorners[i].y;
  245.         if(BoxCorners[i].z<Box->Corners[0].z) Box->Corners[0].z = BoxCorners[i].z;
  246.         if(BoxCorners[i].x>Box->Corners[1].x) Box->Corners[1].x = BoxCorners[i].x;
  247.         if(BoxCorners[i].y>Box->Corners[1].y) Box->Corners[1].y = BoxCorners[i].y;
  248.         if(BoxCorners[i].z>Box->Corners[1].z) Box->Corners[1].z = BoxCorners[i].z;
  249.         }
  250.     }
  251.     else if(Obj->BoundType == BOUND_SPHERE) {
  252.         Sphere = (SPHERE *)Obj->Bound;
  253.         ForwdTransformPoint(&Sphere->Centre, Trans);
  254.         MaxRadius = Sphere->r;
  255.         if(Trans->NumTransforms>0) {
  256.         for(i=0;i<Trans->NumTransforms;i++) {
  257.             Radius.x = Radius.y = Radius.z = MaxRadius;
  258.             if(Trans->Entry[i].Type == TRANSFORM_SCALE) {
  259.             Radius.x *= Trans->Entry[i].Values.x;
  260.             Radius.y *= Trans->Entry[i].Values.y;
  261.             Radius.z *= Trans->Entry[i].Values.z;
  262.             MaxRadius = Radius.x;
  263.             if(Radius.y>MaxRadius) MaxRadius = Radius.y;
  264.             if(Radius.z>MaxRadius) MaxRadius = Radius.z;
  265.             }
  266.         }
  267.         }
  268.         Sphere->r = MaxRadius;
  269.     }
  270. }
  271.  
  272.  
  273. /* ---------------------------------------------------------------------
  274.     RemoveAllUselessTextureTransforms() will remove texture transforms
  275.     from textures that do not contain patterns or images.
  276.    --------------------------------------------------------------------- */
  277.  
  278. void RemoveAllUselessTextureTransforms(void)
  279. {
  280.     int    i;
  281.  
  282.     for(i=0;i<NumObjects;i++)
  283.         RemoveUselessTextureTransforms(ObjectArray[i]);
  284. }
  285.  
  286.  
  287.  
  288. void RemoveUselessTextureTransforms(OBJECT *Obj)
  289. {
  290.     if(Obj->ShapeType == SHAPE_CSG) {
  291.         RemoveUselessTextureTransforms(((CSG *)Obj->Shape)->Object1);
  292.         RemoveUselessTextureTransforms(((CSG *)Obj->Shape)->Object2);
  293.     }
  294.     else {
  295.         if(    (Obj->Texture.Pattern == PATTERN_NONE) && 
  296.         (Obj->Texture.ImageType == IMG_NONE)) {
  297.         ClearTransform(&Obj->Texture.Transform);
  298.         }
  299.     }
  300. }
  301.  
  302. /* ---------------------------------------------------------------------
  303.     ForwdTransformPoint()  I needed this, so here it is...
  304.    --------------------------------------------------------------------- */
  305.  
  306. void ForwdTransformPoint(POINT *Point, TRANSFORM *Trans)
  307. {
  308.     VECTOR    tempv;
  309.     int    i;
  310.  
  311.     if(Trans->NumTransforms>0) {
  312.         for(i=0;i<Trans->NumTransforms;i++) {
  313.         switch(Trans->Entry[i].Type) {
  314.             case TRANSFORM_SCALE:
  315.             tempv=Trans->Entry[i].Values;
  316.             Point->x*=tempv.x; Point->y*=tempv.y; Point->z*=tempv.z;
  317.             break;
  318.             case TRANSFORM_MOVE:
  319.             AddVector((VECTOR *)Point,(VECTOR *)Point,&Trans->Entry[i].Values);
  320.             break;
  321.             case TRANSFORM_ROTATE:
  322.             RotatePoint(Point,&Trans->Entry[i].Values);
  323.             break;
  324.             case TRANSFORM_NONE:
  325.             default:
  326.             break;
  327.         }
  328.         }
  329.     }
  330. }
  331.